/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package E_explicito_EstaticoLICH;


/**
 *
 * @author rafaelob
 */
public class TabelaHash {

    private int Rpoint;
    private int tamanhoTabela;
    private int areaPrimaria;
    private Celula celulas[];
    private double addressFactor;

    public TabelaHash(int tamanho, double addressFactor) {
        celulas = new Celula[tamanho];
        this.tamanhoTabela = tamanho;
        this.addressFactor = addressFactor;
        for (int i = 0; i < tamanho; i++) { //Preenche a tabela com as células de acordo com o tamanho da tabela hash
            celulas[i] = new Celula(i);
        }
        Rpoint = tamanhoTabela - 1;//O ponteiro será posicionado na última posição da tabela.
        areaPrimaria = (int) Math.round(this.addressFactor * tamanhoTabela);//Inteiro mais próximo

    }

    public int getAreaPrimaria() {
        return areaPrimaria;
    }

    public Celula getCelula(int posicao) {
        return celulas[posicao];
    }

    private int getIndex(int chave) { //calcula a função hash associada a essa chave
        return chave % areaPrimaria;
    }

    private void atualizaRpoint() {
        do {
            if (celulas[Rpoint].getRecord() == null)//Se a posição que o Rpoint aponta está vazia, então não precisamos atualizá-lo
            {
                break;
            }
            this.Rpoint--; //Decrementamos até achar uma posição vazia, ou a Tabela está cheia se Rpoint for < 0
        } while (this.Rpoint >= 0);
    }

    public int insertion(int chave) {
        //Atualiza o Rpoint até achar uma posição vazia

        Record record = new Record(chave);
        int index = getIndex(chave);
        if (celulas[index].insertRecord(record)) {
            return 0; // inserido sem colisão
        } else { //Se houve colisão, vamos tratá-la
            atualizaRpoint();
            if (Rpoint < 0) {
                return -1; //Tabela Cheia
            } else {
                Celula atual = celulas[index]; //Variável auxiliar para percorrer a lista
                Celula proximo = atual.getPoint(); //Variável auxiliar
                Celula temp; //Variável Auxiliar
                while (proximo != null) {
                    temp = proximo;
                    proximo = atual.getPoint();
                    atual = temp;
                }
                celulas[Rpoint].insertRecord(record); //Insere o registro no local vazio
                atual.setPoint(celulas[Rpoint]); // Atualiza o ponteiro do posição anterior dessa lista
                Rpoint--; //Decrementando o Rpoint
                return 1; //inserido com Colisão
            }

        }
    }

    public int search(int chave) {
        int index = getIndex(chave);
        int acessos = 1;
        Celula auxiliar = celulas[index]; //Variável auxiliar para percorrer al ista

        while ((!auxiliar.searchRecord(chave)) && auxiliar.getPoint() != null) {
            auxiliar = auxiliar.getPoint();
            acessos++;
        }
        return acessos;


    }
}


